[小ネタ] WSL環境からVisual Studio Codeのリモート起動を行う際のひと工夫
しばたです。
Visual Studio Code(以後VS Code)をインストール済みのWindows環境において、デフォルト設定であればWSL内部からcode
コマンドを実行するとリモート開発の設定がよしなに行われWSL内部のファイルを容易に編集できます。
WSL内部から code コマンドを実行するとホスト側で編集できる
これはWSLのデフォルトでWindowsホスト側のPATH環境変数が共有されており、WSL内部からホスト側のVS Codeバイナリ(code
コマンド)を呼び出せるため実現可能となっています。
ただ、WSLではPATH環境変数を共有しない設定も可能であり、この場合はホスト側のcode
コマンドを呼び出せないためエラーになってしまいます。
# PATH環境変数の共有をしない設定
[interop]
appendWindowsPath = false
/etc/wsl.conf
の設定内容次第でcode
コマンドの起動に失敗しVS Codeを開くことができません。
ホスト側の code コマンドを呼び出せないためエラーになる
本記事ではこの様な「PATH環境変数を共有しない」環境での代替策とちょっとした工夫について解説します。
前提条件
以降の内容は次の前提条件で動作検証しています。
- Windows 11 Pro (23H2) 環境
- User Installで最新のVS Codeをインストール済み + Remote Development拡張インストール済み
- WSL2にUbuntuをインストールして初期設定済み
- ログインシェルはデフォルトのBashのまま
- wsl.conf の設定で環境変数の共有をしない様にしている
対策1. WSL内部のPATH環境変数を自分で設定する
「すべてのPATHが共有されるのは困るが、VS CodeのPATHだけなら共有しても良い」のであれば、WSL内部設定でVS CodeのPATHを追加するのが手っ取り早いでしょう。
たとえばWindowsホスト側のVS Codeが
C:\Users\shibata\AppData\Local\Programs\Microsoft VS Code\bin
にインストールされている場合[1]、WSL内部から見ると
/mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin
というパスになります。
このため、例えばBashを使っている場合は~/.profile
か~/.bashrc
に
# VS Code用のPATHを追加
export PATH=$PATH:'/mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin'
といった感じでPATHを追加してやればエラーを解消できます。
ひと工夫してみる
これはこれで問題無いのですが、/c/Users/shibata/
の部分でユーザー名が決め打ちになっており、個人的にはもう少し汎用的な記述にしたいところです。
汎用的にするためにはプログラム的にユーザー情報を取得する必要がありますが、WSL内部からWindowsホスト側のユーザー情報を直接取得する手段が無いため、ホスト側のプログラムを実行した結果を取り込む形で実現することにしました。
取得する情報に応じて実行内容は変わりますが、今回はホスト側のUSERPROFILE
環境変数の値を取得することにしました。
コマンドプロンプトから環境変数を得るのが一番手っ取り早そうだったのでWSL内部から次のコマンドを実行してやります。
# WSLからコマンドプロンプトを起動し、ホスト側の USERPROFILE 環境変数を取得
/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null
ちょっと変わった記述になっていますが、コマンドプロンプトでは末尾に改行を出力しないecho -n
に相当するコマンドが無いためSET /P
を代替に使っています。
加えてコマンドプロンプト起動時にカレントディレクトリに関する警告が出るので2>/dev/null
しています。
実行結果は以下となり期待通りに情報が取れています。
$ /mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null
C:\Users\shibata
ただ、これだとパスの表記がWindowsの記法なのでwslpath
コマンドを使ってLinuxの記法に変換してやります。
# wslpathコマンドでパスの形式を変換
wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null)
結果はこんな感じでLinuxのパス表記に変換されます。
# C:\Users\shibata → /mnt/c/Users/shibata に変換される
$ wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null)
/mnt/c/Users/shibata
最終的に以下の形でPATHを追加してやれば完成です。
# より汎用的な形でPATHを追加
export PATH=$PATH:"$(wslpath $(/mnt/c/WINDOWS/system32/cmd.exe /c 'SET /P X=%USERPROFILE%<NUL' 2>/dev/null))/AppData/Local/Programs/Microsoft VS Code/bin"
これで期待通りWindowsホスト側のVS Codeに対してだけPATHを追加できました。
# 環境変数を確認
$ printenv PATH | tr ':' '\n'
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/snap/bin
/mnt/c/Users/shibata/AppData/Local/Programs/Microsoft VS Code/bin
余談 : 他シェルの場合
Bash以外のシェルの場合はそのシェルに応じた記述に変えてやる必要があります。
たとえば私が常用しているNushellだと次の記述をconfig.nu
に追加する形になります。
# Nushell on WSLでの設定例
let host_user_profile = wslpath (/mnt/c/WINDOWS/system32/cmd.exe /q /c 'SET /P X=%USERPROFILE%<NUL' | complete | get stdout)
$env.PATH = ($env.PATH | append $"($host_user_profile)/AppData/Local/Programs/Microsoft VS Code/bin")
対策2. ホスト側からVS Code Remoteを実行する
WSL側のPATHを一切変更したくない場合やWSLからWindowsホストのプログラムを実行できない場合はホスト側からcode
コマンドを実行する形でも代替可能です。
上記ドキュメントによればcode
コマンドの--remote
パラメーターでWSL内部のファイルを開けます。
code --remote wsl+<distro name> <path in WSL>
WSLのディストリビューション名はwsl --list
コマンドから取得できます。
実行結果は下図の様になり、期待通りの動作をしてくれます。
# ディストリビューション名が Ubuntu-22.04 の場合の実行例
PS C:\> code --remote wsl+Ubuntu-22.04 /home/username/test
最後に
以上となります。
本記事にある事象と対策自体は既出のものですが、PATHの書き方をもう少しなんとかしたいと思い頑張ってみました。
User Installerでインストールした場合のパスです ↩︎